<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Cpp expression question renderer class.
 *
 * @package     cppexpression
 * @author      Khrzhanovskaya Olga, Sychev Oleg
 * @copyright   &copy; 2014 Oleg Sychev, Volgograd State Technical University
 * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */


defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once($CFG->dirroot . '/question/type/shortanswer/renderer.php');

/**
 * Generates the output for cpp expression questions.
 *
 * @copyright  2014 Khrzhanovskaya Olga
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class qtype_cppexpression_renderer extends qtype_shortanswer_renderer {

    public function correct_response(question_attempt $qa) {
        $question = $qa->get_question();

        $answer = $question->get_correct_response();
        if (!$answer) {
            return '';
        }
        return get_string('correctansweris', 'qtype_shortanswer', $answer['answer']);
    }

    public function feedback(question_attempt $qa, question_display_options $options) {

        $feedback = '';

        $question = $qa->get_question();
        $behaviour = $qa->get_behaviour();
        $currentanswer = $qa->get_last_qt_var('answer');
        if (!$currentanswer) {
            $currentanswer = '';
        }
        $br =  html_writer::empty_tag('br');

        if (is_a($behaviour, 'behaviour_with_hints')) {

            // for interactivehints check existing variants of options in question_attempt_step data
            if(get_class($behaviour) == 'qbehaviour_interactivehints') {
                $hints = $this->get_qa_hints($qa);

                foreach($hints as $hintkey){
                    $feedback .= $this->render_hint($question, $hintkey, $qa, $options, $currentanswer);
                 }
            }
            else { // adaptivehints
                $hints = $question->available_specific_hints($currentanswer);
                $hints = $behaviour->adjust_hints($hints);

                foreach ($hints as $hintkey) {
                    if( $qa->get_last_step()->has_behaviour_var('_render_'.$hintkey)) {
                        $feedback .= $this->render_hint($question, $hintkey, $qa, $options, $currentanswer);
                    }
                }
            }
        }
        $output = parent::feedback($qa, $options);
        return $feedback.$output;
    }

    /**
     * Generate feedback of analyser. Feedback contains information about errors
     * if analyzer cann't process answer.
     *
     * @param $question question.
     * @param $hintkey available hints as hintey.
     * @param $qa the question attempt to display.
     * @param $options controls what should and should not be displayed.
     * @param $answer last student response.
     * @return feedback as HTML fragment.
     */
    private function render_hint($question, $hintkey, $qa, $options, $answer) {
        $feedback = '';
        $br =  html_writer::empty_tag('br');

        $hintobj = $question->hint_object($hintkey);
        $hint =  $hintobj->render_hint($this, $qa, $options, array('answer' => $answer));
        if(gettype($hint) == 'string') { // moodle hint
            $feedback .= $hint . $br;
        } else {                        // analyser hint
            if(count($hint['errors'])) {
                foreach($hint['errors'] as $error) {
                    $feedback .= $error->analyzer . ' error: ' . $error->errormsg . $br;
                }
            } else {
                $feedback .= $hint['hint']->hint . $br;
            }
        }
        return $feedback;
    }

    /**
     * Gereate array of hintkeys of available hints parsing fields of question_attempt object.
     * It is used for interactivehints behaviour.
     *
     * @param question_attempt $qa the question attempt to display.
     * @return array of hintkeys.
     */
    private function get_qa_hints(question_attempt $qa) {

        $qtype = new qtype_cppexpression;
        $hintanalyzernames = $qtype->get_hint_analyzers_names();

        // generate all analyzer's names
        $arr = array();
        foreach($hintanalyzernames as $hintanalyzername) {
            $analyzerclassname = 'qtype_cppexpr_' . $hintanalyzername . 'analyzerhint';
            $analyzer = new $analyzerclassname('', '');
            $curarr = array( $hintanalyzername => count($analyzer->get_options()) );
            $arr = array_merge($arr,$curarr);
        }

        $result = array();
        foreach($arr as $name => $count) {
            $curres = array();
            // add in array <exist option + current>
            foreach($result as $curval) {
                for($i = 1; $i <= $count; $i++){
                    $optionsstr = $curval . '\n' . $name . '_' . $i;
                    if($qa->get_last_step()->has_qt_var($optionsstr)) {
                        $hintsstr = str_replace('-_render_','',$optionsstr);
                        return explode('\n',$hintsstr);
                    }
                    $curres[] = $optionsstr;
                }
            }
            // add in array pure current option
            for($i = 1; $i <= $count; $i++){
                $optionsstr = '-_render_' . $name . '_' . $i;
                if($qa->get_last_step()->has_qt_var($optionsstr)) {
                    $hintsstr = str_replace('-_render_','',$optionsstr);
                    return explode('\n',$hintsstr);
               }
               $result[] = $optionsstr;
           }
           $result = array_merge($result, $curres);
        }
        return array();
    }
}
